// 从 'vue' 导入 Composition API 中的 ref、unref、getCurrentInstance 和 watch 函数
import { ref, unref, getCurrentInstance, watch } from 'vue';
// 从 '@/utils/env' 导入 isProdMode 函数，用于判断是否为生产环境
import { isProdMode } from '@/utils/env';
// 从 '../type' 导入之前定义的 ModalMethods 和 UseModalReturnType 类型
import { ModalMethods, UseModalReturnType } from '../type';
// 从 '@/utils' 导入 getDynamicProps 函数，用于获取动态属性
import { getDynamicProps } from '@/utils';
// 从 '@vueuse/core' 导入 tryOnUnmounted 函数，用于在组件卸载时执行清理操作
import { tryOnUnmounted } from '@vueuse/core';

// useModal 函数，接收 props 参数，返回一个数组，包含 register 方法和 ModalMethods 对象
export function useModal(props): UseModalReturnType {
  // 使用 ref 创建一个可响应的 modalRef，初始值为 null
  const modalRef = ref<Nullable<ModalMethods>>(null);
  // 获取当前组件实例
  const currentInstance = getCurrentInstance();

  // getInstance 函数，用于获取 modalRef 中的实例
  const getInstance = () => {
    const instance = unref(modalRef.value);
    if (!instance) {
      console.error('useModal instance is undefined!'); // 如果实例未定义，则输出错误信息
    }
    return instance;
  };

  // register 函数，用于注册弹窗实例
  const register = (modalInstance: ModalMethods) => {
    // 如果是生产环境，则在组件卸载时清理 modalRef
    isProdMode() &&
      tryOnUnmounted(() => {
        modalRef.value = null;
      });
    // 将 modalInstance 赋值给 modalRef
    modalRef.value = modalInstance;
    // 如果当前组件实例存在，则触发 'register' 事件
    currentInstance?.emit('register', modalInstance);

    // 使用 watch 监听 props 的变化，并更新 modalInstance 的属性
    watch(
      () => props,
      () => {
        props && modalInstance.setProps(getDynamicProps(props)); // 使用 getDynamicProps 函数获取动态属性并设置
      },
      {
        immediate: true, // 立即执行
        deep: true, // 深度监听
      },
    );
  };

  // 定义 methods 对象，包含弹窗的操作方法
  const methods: ModalMethods = {
    // 设置弹窗属性
    setProps: (props): void => {
      getInstance()?.setProps(props);
    },
    // 打开弹窗
    openModal: () => {
      getInstance()?.openModal();
    },
    // 关闭弹窗
    closeModal: () => {
      getInstance()?.closeModal();
    },
    // 设置子组件加载状态
    setSubLoading: (status) => {
      getInstance()?.setSubLoading(status);
    },
  };

  // 返回一个数组，包含 register 方法和 methods 对象
  return [register, methods];
}
